package managers;

import br.com.caelum.vraptor.ioc.Component;
import entities.BidsEntity;
import entities.ProductStatus;
import entities.ProductsEntity;
import entities.UsersEntity;
import models.BidInfo;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

@Component
public class ProductsManager {
    private final Session hibernateSession;

    public ProductsManager(Session hibernateSession) {
        this.hibernateSession = hibernateSession;
    }

    public List<ProductsEntity> getProducts(){
        Query query = hibernateSession.createQuery("FROM ProductsEntity");
        Transaction tx = hibernateSession.beginTransaction();
        List<ProductsEntity> list = (List<ProductsEntity>)query.list();
        tx.commit();

        return list;
    }

    public List<ProductsEntity> getProductsByType(byte type){
        Query query = hibernateSession.createQuery("FROM ProductsEntity p WHERE p.type = :type")
                .setParameter("type", type);

        Transaction tx = hibernateSession.beginTransaction();
        List<ProductsEntity> list = (List<ProductsEntity>)query.list();
        tx.commit();

        return list;
    }

    public ProductsEntity getProductById(int id){
        Transaction tx = hibernateSession.beginTransaction();
        ProductsEntity entity = (ProductsEntity)hibernateSession.get(ProductsEntity.class, id);
        tx.commit();

        return entity;
    }

    public void saveProduct(ProductsEntity product){
        Transaction tx = hibernateSession.beginTransaction();
        hibernateSession.saveOrUpdate(product);
        tx.commit();
    }

    public List<BidInfo> getBids(int productId){
        Query query = hibernateSession.createQuery("SELECT new models.BidInfo(b.user.userName, b.price, b.dateCreated) " +
                "FROM BidsEntity b WHERE b.product.id = :productId")
            .setParameter("productId", productId);

        Transaction tx = hibernateSession.beginTransaction();
        List<BidInfo> list = (List<BidInfo>)query.list();
        tx.commit();

        return list;
    }

    public List<BidInfo> getBids(int productId, String userName){
        Query query = hibernateSession.createQuery("SELECT new models.BidInfo(b.user.userName, b.price, b.dateCreated)" +
                " FROM BidsEntity b WHERE b.product.id = :productId AND b.user.userName = :userName")
                .setParameter("productId", productId)
                .setParameter("userName", userName);

        Transaction tx = hibernateSession.beginTransaction();
        List<BidInfo> list = (List<BidInfo>)query.list();
        tx.commit();

        return list;
    }

    public Float getMaxBid(int productId){
        Query query = hibernateSession.createQuery("SELECT max(b.price) FROM BidsEntity b WHERE b.product.id = :productId")
                .setParameter("productId", productId);

        Transaction tx = hibernateSession.beginTransaction();
        Float result = (Float)query.uniqueResult();
        tx.commit();

        return result;
    }

    public void placeBid(int productId, int userId, float price) {
        BidsEntity bid = new BidsEntity();

        ProductsEntity pr = new ProductsEntity();
        pr.setId(productId);

        UsersEntity user = new UsersEntity();
        user.setUserId(userId);

        bid.setProduct(pr);
        bid.setUser(user);
        bid.setPrice(price);

        Transaction tx = hibernateSession.beginTransaction();
        hibernateSession.saveOrUpdate(bid);
        tx.commit();
    }

    public void updateProductStatus(int productId, byte status){
        Transaction tx = hibernateSession.beginTransaction();
        ProductsEntity product = (ProductsEntity)hibernateSession.get(ProductsEntity.class, productId);
        product.setStatus(status);

        if(status == ProductStatus.ENDED){
            Date now = new Date();
            product.setDateEnd(new Timestamp(now.getTime()));
        }

        hibernateSession.update(product);
        tx.commit();
    }
}
